Automated Sized-Type Inference and Complexity Analysis

نویسندگان

  • Martin Avanzini
  • Ugo Dal Lago
چکیده

Index Language. Unlike in [8], where indices are formed over naturals and addition, we keep the index language abstract. This allows for more flexibility, and ultimately for a better intensionality. Indeed, having the freedom of not adopting a fixed index language is known to lead towards completeness [5]. Polymorphic Recursion over Sizes. Type inference in functional programming languages, such as Haskell or OCaml, is restricted to parametric polymorphism in the form of let-polymorphism. Recursive definitions are checked under a monotype, thus, types cannot change between recursive calls. Recursive 10 Automating Sized-Type Inference and Complexity Analysis functions that require full parametric polymorphism [9] have to be annotated in general, as type inference is undecidable in this setting. Let-polymorphism poses a significant restriction in our context, because sized types considerably refine upon simple types. Consider for instance the usual tail-recursive definition of list reversal depicted in Figure 1. With respect to the annotated sized types, in the body of the auxiliary function rev defined on line 4, the type of the second argument to rev will change from List j α (the assumed type of ys) to List j+1 α (the inferred type of x : ys). Consequently, rev is not typeable under a monomorphic sized type. Thus, to handle even such very simple functions, we will have to overcome let-polymorphism, on the layer of size annotations. To this end, conceptually we allow also recursive calls to be given a type polymorphic over size variables. This is more general than the typing rule for recursive definitions found in more traditional systems [8, 3]. Higher-ranked Polymorphism over Sizes. In order to remain decidable, classical type inference systems work on polymorphic types in prenex form ∀~α.τ , where τ is quantifier free. In our context, it is often not enough to give a combinator a type in prenex form, in particular when the combinator uses a functional argument more than once. All uses of the functional argument have to be given then the same type. In the context of sized types, this means that functional arguments can be applied only to expressions whose attributed size equals. This happens for instance in recursive combinators, but also non-recursive ones such as the following function twice f x = f ( f x). A strong type-system would allow us to type the expression twice Succ with a sized type Natc→ Natc+2. A (specialised) type in prenex form for twice, such as twice :: ∀i. (Nati→ Nati+1)→ Nati→ Nati+2 , would immediately yield the mentioned sized type for twice Succ. However, we will not be able to type twice itself, because the outer occurrence of f would need to be typed as Nati+1→ Nati+2, whereas the type of twice dictates that f has type Nati→ Nati+1. The way out is to allow polymorphic types of rank higher than one when it comes to size variables, i.e. to allow quantification of size variables to the left of an arrow at arbitrary depth. Thus, we can declare twice :: ∀i. (∀ j.Nat j→ Nat j+1)→ Nati→ Nati+2 . As above, this allows us to type the expression twice Succ as desired. Moreover, the inner quantifier permits the two occurrences of the variable f in the body of twice to take types Nati → Nati+1 and Nati+1→ Nati+2 respectively, and thus twice is well-typed. The Ticking Transformation. Our type system only reflect upon one extensional properties of programs, namely how the size of the output relates to the size of the input. Runtime analysis can however be reduced to size analysis, e.g. via a ticking transformation. This transformation takes a program P and translates it into another program P̂. The transformed program behaves like P, but additionally computes also the runtime on the given input. Technically, the latter is achieved by threading through the computation a counter, the clock, which is advanced whenever an equation of P fires. A k-ary function f :: τ1→ ··· → τk→ τ of P will be modeled in P̂ by a function f̂k :: 〈τ1〉 → ·· · → 〈τk〉 → C→ 〈τ〉×C, where C is the type of the clock. Here, 〈ρ〉 enriches functional types ρ with clocks accordingly. The function f̂k behaves in essence like f, but advances the threaded clock suitably. The clock-type C encodes the running time in unary notation. The size of the clock thus corresponds to its value. Our type system can estimate the size of the clock in the ticked program P̂, and thus the runtime of the considered program P. Noteworthy, this transformation is straight forward to implement. M. Avanzini & U. Dal Lago 11 1 foldr :: ∀αβ . ∀ jkl. (∀i. α → Listi β → Listi+ j β )→ Listk β → Listl α → Listl· j+k β 2 foldr f b [] = b 3 foldr f b (x : xs) = f x (foldr f b xs) 4 product :: ∀αβ . ∀i j. Listi α → List j β → Listi· j (α×β ) 5 product ms ns = foldr (λ m ps. foldr (λ n. (:) (m,n)) ps ns) [] ms Figure 2: Sized type annotated program computing the cross-product of two lists. 3 A Worked Out Example In this section we give a nontrivial example. The sized type annotated program is given in Figure 2. The function product computes the cross-product [ (m,n) |m ∈ms,n ∈ ns ] for two given lists ms and ns. It is defined in terms of two folds. The inner fold appends, for a fixed element m, the list [ (m,n) | n ∈ ns ] to an accumulator ps, the outer fold traverses this function over all elements m from ms. In a nutshell, checking that a function f is typed correctly amounts to checking that all its defining equations are well-typed, i.e. under the assumption that the variables are typed according to the type declaration of f, the right-hand side of the equation has to be given the corresponding return-type. Of course, all of this has to take pattern matching into account. Let us illustrate this on the recursive equation of foldr given in Line 3 in Figure 2. Throughout the following, we denote by s :τ that the term s has type τ . To show that the equation is well-typed, let us assume the following types for arguments: f :∀i. α → Listi β → Listi+ j β , b :Listk β , x :α and xs :Listm α for arbitrary size-indices j,k,m. Under these assumptions, the left-hand side has type List(m+1)· j+k β , taking into account that the recursion parameter x : xs has size m+1. To show that the equation is well-typed, we verify that the right-hand side can be attributed the same sized type. To this end, we proceed inside out as follows. 1. We instantiate the polymorphic type of foldr and derive foldr :(∀i. α → Listi β → Listi+ j β )→ Listk β → Listm α → Listm· j+k β ; 2. from this and the above assumptions we get foldr f b xs :Listm· j+k β ; 3. by instantiating the quantified size variable i in the assumed type of f with the index term m · j+ k we get f :α → Listm· j+k β → List(m· j+k)+ j β ; 4. from the last two steps we finally get f x (foldr f b xs) :List(m+1)· j+k β . We will not explain the type checking of the remaining equations. However, we would like to stress two crucial points concerning the type of foldr. First of all, we could only suitably type the two occurrences of f in the body of foldr since f was given a type polymorphic in the size of its arguments. Secondly, notice that the variable j in the type of foldr relates the size of the result of the argument function to the size of the result of foldr. This turns out to be a very useful feature in our system, as any expression that can be given a type of the form τ → Listk ρ → Listk+m ρ is applicable to foldr, even if m depends on the environment of the call-site. In particular, we will be able to instantiate both λ -abstractions in the definition of product to such a type, despite that for the outer abstraction, m depends on the size of the captured variable ns. It is also worthy of note that the example is only typable since the most general type for foldr, namely (α → β → β )→ β → List α → β has been sufficiently instantiated. Our implementation HoSA performs such an instantiation when required, and can infer the sized type of product specified above automatically. 12 Automating Sized-Type Inference and Complexity Analysis 4 Applicative Programs and Simple Types We restrict our attention to a small prototypical, strongly typed functional programming language. For the sake of simplifying presentation, we impose a simple, monomorphic, type system on programs, which does not guarantee anything except a form of type soundness. We will only later in this paper introduce sized types proper. Our theory can be extended straightforwardly to an ML-style polymorphic type setting. Here, such an extension would only distract from the essentials. Indeed, our implementation allows polymorphic function definitions. Let B denote a finite set of base types B,C, . . . . Simple types are inductively generated from B ∈B: (simple types) τ,ρ,ξ ::= B | τ → ρ . We follow the usual convention that→ associates to the right. Let X denote a countably infinite set of variables, ranged over by metavariables like x, y. Furthermore, let F and C denote two disjoint sets of symbols, the set of functions and constructors, respectively, all pairwise distinct with elements from X . Functions and constructors are denoted in teletype font. We keep the convention that functions start with a lower-case letter, whereas constructors start with an upper-case letter. Each symbol s ∈X ∪F ∪C has a simple type τ , and when we want to insist on that, we write sτ instead of just s. Furthermore, each symbol sτ1→···→τn→ρ ∈F ∪C is associated a natural number ar(s) ≤ n, its arity. The set of terms, patterns and values over functions f ∈F , constructors C ∈ C and variables x ∈X is inductively generated as follows. Here, each term receives implicitly a type, in Church style. Below, we employ the usual convention that application associates to the left. (terms) s, t ::= xτ | fτ | Cτ | (sτ→ρ tτ)ρ (patterns) p,q ::= xτ | Cτ1→···τn→B pτ1 1 · · · p τn n ; (values) u,v ::= Cτ1→···→τn→τ uτ1 1 · · ·u τn n | fτ1→···→τm→τm+1→τ u τ1 1 · · ·u τm m ; A program P over functions F and constructors C defines each function f ∈F through a finite set of equations lτ = rτ , where l is of the form f p1 · · · par( f ). We put the usual restriction on equations that each variable occurs at most once in l, i.e. that l is linear, and that the variables of the right-hand side r are all included in l. To keep the semantics short, we do not impose any order on the equations. Instead, we require that left-hand sides defining f are all pairwise non-overlapping. This ensures that our programming model is deterministic. We assume call-by-value semantics. The call-by-value reduction relation of a program P is denoted by − →P and defined in the expected way, see [2]. Some remarks are in order before proceeding. As standard in functional programming, only values of base type can be destructed by pattern matching. In a pattern, a constructor always needs to be fully applied. We excluded λ -abstractions from our language. In our setting, abstractions would only complicate the presentation without improving on expressivity. They can always be lifted to the top-level. Similarly, conditionals and case-expressions would not improve upon expressivity. 5 Sized Types and Their Soundness This section is devoted to introducing the main object of study of this paper, namely a sized type system for the applicative programs that we introduced in Section 4. We have tried to keep the presentation of the relatively involved underlying concepts as simple as possible. M. Avanzini & U. Dal Lago 13 Indices. As a first step, we make the notion of size index, with which we will later annotate data types, precise. Let G denote a set of first-order function symbols, the index symbols. Any symbol f ∈ G is associated with a natural number ar(f), its arity. The set of index terms is generated over a countable infinite set of index variables i ∈ V and index symbols f ∈ G . (

برای دانلود رایگان متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

منابع مشابه

Automating Sized Type Inference for Complexity Analysis (Technical Report)

This paper introduces a new methodology for the complexity analysis of higher-order functional programs, which is based on three ingredients: a powerful type system for size analysis and a sound type inference procedure for it, a ticking monadic transformation, and constraint solving. Noticeably, the presented methodology can be fully automated, and is able to analyse a series of examples which...

متن کامل

Inferring static non-monotonically sized types through testing

We propose a size analysis algorithm that combines testing and type checking to automatically obtain static output-on-input size dependencies for first-order functions. Attention is restricted to functions for which the size of the result is strictly polynomial, not necessarily monotonic, in the sizes of the arguments. To infer a size dependency, the algorithm generates hypotheses for increasin...

متن کامل

Automated Analysis of Pressure Build up Tests Affected by Phase Redistribution

Analytical Solutions and type curves for the constant rate radial flow of fluid in both conventional and naturally fractured reservoirs including the effect of wellbore phase redistribution are presented. An automated procedure for non-linear least square minimization using the analytical solutions and their derivatives with respect to the unknown parameters developed to analyze the pressur...

متن کامل

Multivariate Amortised Resource Analysis for Term Rewrite Systems

We study amortised resource analysis in the context of term rewrite systems. We introduce a novel amortised analysis based on the potential method. The method is represented in an inference system akin to a type system and gives rise to polynomial bounds on the innermost runtime complexity of the analysed rewrite system. The crucial feature of the inference system is the admittance of multivari...

متن کامل

3D Scene and Object Classification Based on Information Complexity of Depth Data

In this paper the problem of 3D scene and object classification from depth data is addressed. In contrast to high-dimensional feature-based representation, the depth data is described in a low dimensional space. In order to remedy the curse of dimensionality problem, the depth data is described by a sparse model over a learned dictionary. Exploiting the algorithmic information theory, a new def...

متن کامل

Inference for the Type-II Generalized Logistic Distribution with Progressive Hybrid Censoring

This article presents the analysis of the Type-II hybrid progressively censored data when the lifetime distributions of the items follow Type-II generalized logistic distribution. Maximum likelihood estimators (MLEs) are investigated for estimating the location and scale parameters. It is observed that the MLEs can not be obtained in explicit forms. We provide the approximate maximum likelihood...

متن کامل

ذخیره در منابع من


  با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید

عنوان ژورنال:

دوره   شماره 

صفحات  -

تاریخ انتشار 2017